home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Utilities / Programming / EnterAct 3.5 / Minimal App7 ƒ / minimalApp7.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  20.8 KB  |  801 lines  |  [TEXT/KEEN]

  1. /* minimalApp7.c - a do-nothing-but-call Drag_on Modules  application.  by
  2. Ken Earle, 1989/91/92/93. Copyright? Shirley you must be joking.
  3.  
  4. NOTE System 7 is required  to  run  Minimal  App7.  Future  releases  will
  5. incorporate ever more System 7 features.
  6.  
  7. ThinkC project "MinimalApp7.π" outline:
  8.     Options...; <MacHeaders>, Check Pointers, Require Protoypes
  9.     Set Project Type...; File Type APPL, Creator ???? or whatever
  10.     Size Flags:
  11.  
  12.                                                 √MultiFinder-Aware
  13.                                                 √Background Null Events
  14.                                                 √Suspend & Resume Events
  15.  
  16.  
  17.  
  18.                                                  Background Only
  19.                                                  Get FrontClicks
  20.                                                  Accept ChildDiedEvents
  21.  
  22.  
  23.                                                 √32-Bit Compatible
  24.                                                 √HighLevelEvent-Aware
  25.                                                  Accept Remote HighLevelEvents
  26.                                                  Stationery-Aware
  27.                                                  Use TextEdit Services
  28.  
  29.  
  30.  
  31.     Files:
  32.         minimalApp7.c    - in the “Minimal App7 ƒ” folder
  33.         Call_Resource.c - also in the “Minimal App7 ƒ” folder (a copy of
  34.             the other Call_Resource.c file in “code to call Drag_ons”,
  35.             slightly modified for use with Minimal App7)
  36.     Headers: <MacHeaders> <string.h> from THINK C
  37.     Libs: MacTraps, ANSI (the ordinary one, not ANSI a4 etc)
  38.     Resources: MinimalApp7.π.rsrc (just a SICN) in the “Minimal App7 ƒ” folder
  39.  
  40. NOTE place the built Minimal App7 in  the  same  folder  as  the  “Drag_on
  41. Modules” folder, at the same level. Typically this will be where  THINK  C
  42. and EnterAct live.
  43.  
  44. You should see hAWK and Read Resource under the Edit menu  when  you  fire
  45. this up. Options for input will be limited to “Specific file”  with  hAWK,
  46. and neither module will be able to tell this little  application  to  show
  47. you the results of a run - you’ll have to use  a  real  editor  for  that.
  48. Other than that, everything will happen as though you were  calling  these
  49. from EnterAct or some other real application.
  50.  
  51. Once you’re familiar with hAWK, it’s easy to modify a program to take  its
  52. input from a list of files in some specific  file.  For  details  see  the
  53. "hAWK User’s Manual", in the "Other ways of specifying input"  section  of
  54. the "Advanced topics" chapter. For an easy way to run a hAWK program  from
  55. Minimal App7 using  a  list  of  files,  see  the  supplied  hAWK  program
  56. "$MA7_RunClip". Note though that "$MA7_RunClip" works properly only if the
  57. actual program being run does not use preset variables, or if it is OK for
  58. all preset variables to be null.
  59.  
  60. Minimal App7 differs from the earlier Minimal App  primarily  in  that  it
  61. will run only under system  7.  It  supports  concurrent  hAWK  execution,
  62. meaning you can start up Minimal App7, start running a hAWK  program,  and
  63. then switch to some other application and continue working.  Minimal  App7
  64. will notify you when the hAWK program is done.
  65.  
  66. Minimal App7 also supports the "getclip()"  function  in  hAWK.  Since  it
  67. doesn't have a private clip, it passes the system  clip.  Note  that  most
  68. applications do not alter the system clip until you switch out.  This  may
  69. change in the future as a result of AppleScript.
  70.  
  71. To see the hilites of calling Drag_on Modules, search this file for *****
  72. */
  73.  
  74. #include <AppleEvents.h>
  75.  
  76. #include <Traps.h>
  77. #include <GestaltEqu.h>
  78.  
  79. /* kOSEvent is the event number of the suspend/resume and mouse-moved events sent
  80.    by MultiFinder. Once we determine that an event is an OSEvent, we look at the
  81.    high byte of the message sent to determine which kind it is. To differentiate
  82.    suspend and resume events we check the resumeMask bit. */
  83. #define    kOSEvent                app4Evt    /* event used by MultiFinder */
  84. #define    kSuspendResumeMessage    1        /* high byte of suspend/resume event message */
  85. #define    kResumeMask                1        /* bit of message field for resume vs. suspend */
  86. #define    kMouseMovedMessage        0xFA    /* high byte of mouse-moved event message */
  87.  
  88. /*    kExtremeNeg and kExtremePos are used to set up wide open rectangles and regions. */
  89. #define kExtremeNeg                -32768
  90. #define kExtremePos                (32767 - 1) /* required to address an old region bug */
  91.  
  92. #ifndef _Unimplemented
  93. #define    _Unimplemented 0x9F
  94. #endif
  95. #ifndef _WaitNextEvent
  96. #define _WaitNextEvent 0x60
  97. #endif
  98.  
  99.  
  100. #ifndef NULL
  101. #define NULL        ((void *) 0)
  102. #endif
  103.  
  104. #define        APPLEID                15
  105. #define        FILEID                16
  106. #define        EDITID                17
  107. #define        QUIT                12
  108.  
  109. #define        WindowDataPtr        WindowPtr
  110.  
  111. /* Augmented record of event - see SetEventDetails() */
  112. struct EventDetails
  113.     {
  114.     EventRecord        event;            /* IM 1 pg 249 */
  115.     WindowPtr        mouseDownWindow;/* not necessarily front window */
  116.     Point            localWhere;        /* mousedown point in local coordinates */
  117.     ControlHandle    whichControl;
  118.     short                whatPart;
  119.     Boolean            shiftDown, capsLockDown, optionDown, commandDown, doubleClick;
  120.     };
  121. typedef struct EventDetails EventDetails;
  122.  
  123. /* --------- useful globals ---------------- */
  124. MenuHandle      appleMenu, fileMenu, editMenu;
  125. Boolean            gInBackground, gQuitting;
  126. CursHandle        IBeam, Watch;
  127. EventDetails      gEvtDetails;        /* info about latest event */
  128. Boolean            daInFront;             /* for scrap conversion */
  129. /* cursor management, called by all event loops */
  130. RgnHandle    cursorRgn;
  131. static RgnHandle    arrowRgn;
  132. static RgnHandle    iBeamRgn;
  133. /******* to handle concurrent Drag_on Modules, for version 2 or greater. */
  134. Boolean gNotifying; /* hAWK finished with Minimal App in the background. */
  135. Boolean gHawkIsRunning; /* If true, no quitting and less sleeping. */
  136. NMRec    gNotifyRec;
  137.  
  138. /******* The two functions from elsewhere */
  139. /* Call_Resource.c */
  140. extern void InitCallResources(short vRefNumForApp, 
  141.     char *codeFolderName, short menuID);
  142. /* Note "VERSION2" of CallResource() is being used. */
  143. extern void CallResource(short menuID, short item, Boolean concurrent);
  144.  
  145. /* Prototypes for functions defined in this file */
  146. short main(void);
  147. void DoStandardInits(void);
  148. void MakeMenus(void);
  149. Boolean DoMenu(long);
  150. /* Apple event handlers */
  151. pascal OSErr Handle_aevt_oapp(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon);
  152. pascal OSErr Handle_aevt_odoc(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon);
  153. pascal OSErr Handle_aevt_pdoc(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon);
  154. pascal OSErr Handle_aevt_quit(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon);
  155. OSErr MissedAEKeyword(AppleEvent *theAppleEvent);
  156. /* some WNE functions */
  157. void HandleModelessDialog(void);
  158. void SetEventDetails(void);
  159. unsigned long GetSleep(void);
  160. void BlinkTextCursor(void);
  161. void AdjustCursor(Point mouse, RgnHandle region);
  162. Boolean    IsMultiCursorWindow(WindowDataPtr wdPtr);
  163. void SetWatchCursor(void);
  164. /* support functions */
  165. Boolean System7Available(void);
  166. Boolean TrapAvailable(short theTrap);
  167. TrapType GetTrapType(short theTrap);
  168. short NumToolboxTraps(void);
  169. void AEInstallEventHandlers(void);
  170. void SeeIfDAIsFrontWindow(void);
  171. /********* for concurrent mode Drag_on Module (ie hAWK), handle a single event. */
  172. void HandleOneEvent(void);
  173.  
  174. /* Init, and the main event loop. Note there is a "one-shot" event loop
  175. at the bottom of this file, called by hAWK during concurrent execution.
  176. */
  177. short main()
  178.     {
  179.     WindowPtr        whichWindow;
  180.     Point            where;
  181.     short            part, appVRefNum;
  182.     Boolean            gotEvent;
  183.     
  184.     DoStandardInits();
  185.     MakeMenus();
  186.     IBeam = GetCursor(iBeamCursor);
  187.     Watch = GetCursor(watchCursor);
  188.     if (!System7Available())
  189.         {
  190.         SysBeep(2);
  191.         SysBeep(0);
  192.         SysBeep(2);
  193.         ExitToShell();
  194.         }
  195.     AEInstallEventHandlers();
  196.     /************* Set up to call Drag_ons */
  197.     if (GetVol(NULL, &appVRefNum))
  198.         appVRefNum = 0;
  199.     InitCallResources(appVRefNum, (Ptr)"\pDrag_on Modules", EDITID);
  200.     
  201.     cursorRgn = NewRgn();        /* we’ll pass WNE an empty region the 1st time thru */
  202.     arrowRgn = NewRgn();
  203.     iBeamRgn = NewRgn();
  204.     
  205.     do /* while not quitting */
  206.         {
  207.         SeeIfDAIsFrontWindow();
  208.         if (gInBackground)
  209.             {
  210.             /* handle being in the background */
  211.             ;
  212.             }
  213.         gotEvent = WaitNextEvent(everyEvent, &gEvtDetails.event, GetSleep(), cursorRgn);
  214.         if (gotEvent)
  215.             {
  216.             SetEventDetails();
  217.             
  218.             AdjustCursor(gEvtDetails.event.where, cursorRgn);
  219.             
  220.             if (IsDialogEvent(&gEvtDetails.event))
  221.                 HandleModelessDialog(); /* not implemented */
  222.             else
  223.                 {
  224.                 switch (gEvtDetails.event.what)
  225.                     {
  226.                 case mouseDown:
  227.                     switch (part = FindWindow(gEvtDetails.event.where,
  228.                                     &gEvtDetails.mouseDownWindow)) 
  229.                         {
  230.                     case inDesk: 
  231.                         ;
  232.                     break;
  233.                     case inMenuBar:
  234.                         gQuitting = DoMenu(MenuSelect(gEvtDetails.event.where));
  235.                     case inSysWindow:
  236.                         SystemClick (&gEvtDetails.event, gEvtDetails.mouseDownWindow);
  237.                     break;
  238.                     case inDrag:
  239.                     break;
  240.                     case inZoomIn:
  241.                     case inZoomOut:
  242.                     break;
  243.                     case inGrow:
  244.                     break;
  245.                     case inGoAway:
  246.                     break;
  247.                     case inContent:
  248.                     break;
  249.                     default: 
  250.                     break;
  251.                         } /* switch FindWindow */
  252.                 break;
  253.                 case keyDown:
  254.                 case autoKey:
  255.                     
  256.                 break;
  257.                 case updateEvt:
  258.                     
  259.                 break;
  260.                 case diskEvt:
  261.                     if (HiWord(gEvtDetails.event.message) != noErr)
  262.                         {
  263.                         DILoad();
  264.                         where.h = where.v = 85;
  265.                         DIBadMount(where, gEvtDetails.event.message);
  266.                         }
  267.                 break;
  268.                 case activateEvt:
  269.                     
  270.                 break;
  271.                 case kOSEvent:
  272.                     switch((gEvtDetails.event.message >> 24) & 0xff)
  273.                         {
  274.                     case mouseMovedMessage:
  275.                         BlinkTextCursor();
  276.                     break;
  277.                     case suspendResumeMessage:
  278.                         /* NOT HERE if modeless in front */
  279.                         gInBackground = ((gEvtDetails.event.message & resumeFlag) == 0);
  280.                         /****** Remove notice if hAWK finished while Minimal App was
  281.                         in the background. */
  282.                         if (gNotifying)
  283.                             {
  284.                             NMRemove(&gNotifyRec);
  285.                             if (gNotifyRec.nmIcon)
  286.                                 ReleaseResource(gNotifyRec.nmIcon);
  287.                             gNotifying = FALSE;
  288.                             /* ShowResultsAfterNotify(); -not implemented */
  289.                             }
  290.                     break;
  291.                         } /* switch message */
  292.                 break;
  293.                 case kHighLevelEvent:
  294.                     AEProcessAppleEvent(&gEvtDetails.event);
  295.                 break;
  296.                     } /* switch what */
  297.                 } /* not modeless dialog */
  298.             } /* if got event */
  299.         else
  300.             BlinkTextCursor();
  301.     AdjustCursor(gEvtDetails.event.where, cursorRgn);
  302.         } while (!gQuitting);
  303.     } /* end main() */
  304.  
  305. /* Very routine stuff, though note the stack is enlarged - hAWK needs
  306. a lot of stack. */
  307. void        DoStandardInits()
  308.     {
  309.     short    i;
  310.     EventRecord    event;
  311.     
  312.     /********************* Adjust stack
  313.     - note long StackSpace() returns current room left on stack
  314.     at any time, if there is future trouble...*/
  315.     SetApplLimit(GetApplLimit() - 57344);
  316.     MaxApplZone();
  317.     for (i = 0; i < 18; ++i)
  318.         MoreMasters();
  319.     InitGraf(&thePort);
  320.     InitFonts();
  321.     FlushEvents(everyEvent, 0);
  322.     InitWindows();
  323.     InitMenus();
  324.     TEInit();
  325.     InitDialogs(0L);
  326.     InitCursor();
  327.     for (i = 0; i < 3; ++i)
  328.         EventAvail(everyEvent, &event);
  329.     }/* end DoStandardInits() */
  330.  
  331. void        MakeMenus()
  332.     {
  333.  
  334.     appleMenu = NewMenu(APPLEID,(StringPtr)"\P\24");    
  335.     AppendMenu(appleMenu,(StringPtr)"\P(About nothing...;(-");
  336.     AddResMenu(appleMenu,'DRVR');
  337.     InsertMenu(appleMenu,0);
  338.  
  339.     fileMenu = NewMenu(FILEID,(StringPtr)"\PFile");
  340.     AppendMenu(fileMenu,(StringPtr)"\PNew;Open...;(-;Close;Save;Save as...;Revert;(-;Page Setup...;Print...;(-;Quit/Q");
  341.     InsertMenu(fileMenu,0);    
  342.  
  343.     editMenu = NewMenu(EDITID,(StringPtr)"\PEdit");
  344.     AppendMenu(editMenu,(StringPtr)"\PUndo/Z;(-;Cut/X;Copy/C;Paste/V;Clear");
  345.     InsertMenu(editMenu,0);
  346.  
  347.     DrawMenuBar();
  348.  
  349.     } /* end MakeMenus() */
  350.  
  351. /* DoMenu returns TRUE when quit selected. Quitting is NOT allowed
  352. if hAWK is running. */
  353. Boolean        DoMenu(menuAndItem)
  354. long        menuAndItem;
  355.     {
  356.     short    theItem;
  357.     char    name[64];
  358.     
  359.     theItem = LoWord(menuAndItem);
  360.     switch (HiWord(menuAndItem))
  361.         {
  362.     case APPLEID:
  363.         if (theItem > 1)
  364.             {
  365.             GetItem(appleMenu, theItem, (StringPtr)name);
  366.             OpenDeskAcc((StringPtr)name);
  367.             }
  368.     break;
  369.     case FILEID:
  370.         if (theItem == QUIT)
  371.             {
  372.             if (gHawkIsRunning)
  373.                 {
  374.                 /*********** Request stop Drag_on with <Command><period> first. */
  375.                 SysBeep(2);
  376.                 SysBeep(2);
  377.                 }
  378.             else
  379.                 return(TRUE);
  380.             }
  381.     break;
  382.     case EDITID:
  383.         if (theItem <= 6 && SystemEdit (theItem - 1))
  384.             return(FALSE);
  385.         /***************** Calling all Drag_ons */
  386.         if (theItem > 6)
  387.             CallResource(EDITID, theItem, !gEvtDetails.shiftDown && !gEvtDetails.optionDown);
  388.     break;
  389.     default:
  390.     break;
  391.         }
  392.     HiliteMenu(0);
  393.     return(FALSE);
  394.     } /* end DoMenu() */
  395.  
  396. /* ------------ Apple event handlers --------------- */
  397. /* */
  398. pascal OSErr Handle_aevt_oapp(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
  399.     {
  400.     OSErr    theErr = noErr;
  401.     
  402.     theErr = MissedAEKeyword(theAppleEvent);
  403.     if (theErr) return theErr;
  404.     /* A larger app might open something here;*/
  405.     return theErr;
  406.     }
  407.  
  408. /* Minimal App7 doesn't open documents, but it might some day... */
  409. pascal OSErr Handle_aevt_odoc(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
  410.     {
  411.     AEDesc        theAEDesc;
  412.     AEKeyword    theAEKeyword;
  413.     FSSpec        theSpec;
  414.     DescType    typeCode;
  415.     FInfo        fndrInfo;
  416.     OSErr        theErr;
  417.     Size        actualSize;
  418.     long        i, count;
  419.     Boolean        stationery;
  420.     
  421.     theErr = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &theAEDesc);
  422.     if (theErr) return theErr;
  423.     theErr = MissedAEKeyword(theAppleEvent);
  424.     if (theErr) return theErr;
  425.     theErr = AECountItems(&theAEDesc, &count);
  426.     if (theErr) return theErr;
  427.     for (i = 1; i <= count; ++i)
  428.         {
  429.         theErr = AEGetNthPtr(&theAEDesc, i, typeFSS, &theAEKeyword, &typeCode,
  430.                     (Ptr)&theSpec, sizeof(FSSpec), &actualSize);
  431.         if (theErr) return theErr;
  432.         /* - minimal app doesn't know how to open windows.
  433.         theErr = FSpGetFInfo(&theSpec, &fndrInfo);
  434.         stationery = ((fndrInfo.fdFlags & 0x0800) != 0);
  435.         DoNewWindow(&theSpec, stationery);
  436.         */
  437.         }
  438.     return noErr;
  439.     }
  440.  
  441. /* */
  442. pascal OSErr Handle_aevt_pdoc(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
  443.     {
  444.     return errAEEventNotHandled;
  445.     }
  446.  
  447. /* */
  448. pascal OSErr Handle_aevt_quit(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
  449.     {
  450.     OSErr    theErr;
  451.     
  452.     theErr = MissedAEKeyword(theAppleEvent);
  453.     if (theErr) return theErr;
  454.     if (!gHawkIsRunning) /******** No quitting if hAWK is running. */
  455.         gQuitting = TRUE;
  456.     return noErr;
  457.     }
  458.  
  459. /* The logic here may seem reversed, but the goal is to check if
  460. anything was missed. "NotFound" means the search for something missed
  461. turned up nothing, so all was well.
  462. */
  463. OSErr MissedAEKeyword(AppleEvent *theAppleEvent)
  464.     {
  465.     OSErr        theErr;
  466.     DescType    typeCode;
  467.     Size        actualSize;
  468.     
  469.     theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
  470.                 typeWildCard, &typeCode, NULL, 0, &actualSize);
  471.     if (theErr == errAEDescNotFound)
  472.         return noErr;
  473.     if (theErr == noErr)
  474.         return errAEEventNotHandled;
  475.     return theErr;
  476.     }
  477.  
  478. /* ---------- some WNE functions --------- */
  479. void HandleModelessDialog()
  480.     {
  481.     ;
  482.     }
  483.  
  484. void SetEventDetails()
  485.     {
  486.     static unsigned long     oldTime = 0L;
  487.     static Point            globalWhere = {-1000, -1000};
  488.     unsigned long            newTime;
  489.     short                dH, dV;
  490.     Point            newWhere;
  491.     
  492.     if (gEvtDetails.event.what == mouseDown || gEvtDetails.event.what == keyDown
  493.         || gEvtDetails.event.what == kOSEvent)
  494.         {
  495.         gEvtDetails.shiftDown = (gEvtDetails.event.modifiers & shiftKey) != 0;
  496.         gEvtDetails.capsLockDown = (gEvtDetails.event.modifiers & alphaLock) != 0;
  497.         gEvtDetails.optionDown = (gEvtDetails.event.modifiers & optionKey) != 0;
  498.         gEvtDetails.commandDown = (gEvtDetails.event.modifiers & cmdKey) != 0;
  499.         }
  500.     if (gEvtDetails.event.what == mouseDown)
  501.         {
  502.         Delay(0L, (long *)&newTime);
  503.         newWhere = gEvtDetails.event.where;
  504.         dH = newWhere.h - globalWhere.h;
  505.         dV = newWhere.v - globalWhere.v;
  506.         if (dH < 0)
  507.             dH = -dH;
  508.         if (dV < 0)
  509.             dV = -dV;
  510.         if ((newTime - oldTime) <= GetDblTime()
  511.             && dH <= 5 && dV <= 5)
  512.             gEvtDetails.doubleClick = TRUE;
  513.         else
  514.             gEvtDetails.doubleClick = FALSE;
  515.         globalWhere = newWhere;
  516.         GlobalToLocal (&newWhere);
  517.         gEvtDetails.localWhere = newWhere;
  518.         oldTime = newTime;
  519.         }
  520.     else
  521.         gEvtDetails.doubleClick = FALSE;
  522.     }
  523.  
  524.  
  525. unsigned long GetSleep()
  526.     {
  527.     long        sleep;
  528.     
  529.     /******** Less sleeping if hAWK is running - adjust if you like. */
  530.     if (gHawkIsRunning)
  531.         return(2UL);
  532.     sleep = GetCaretTime();
  533.     return((unsigned long)sleep);
  534.     }
  535.  
  536.  
  537. /*
  538.  * BlinkTextCursor - flash cursor
  539.  */
  540. void BlinkTextCursor()
  541.     {
  542.     WindowDataPtr wdPtr;
  543.     DialogPtr    dP;
  544.     short            item;
  545.     
  546.     /* we only adjust the cursor when we are in front */
  547.     if (gInBackground)
  548.         return;
  549.     wdPtr = (WindowDataPtr) FrontWindow();
  550.     /* Your idle procedure here */
  551.     }
  552.  
  553. /* More than needed here, you can build on this for your own
  554. cursor management. */
  555. void AdjustCursor(Point mouse, RgnHandle region)
  556.     {
  557.     WindowDataPtr wdPtr;
  558.     Rect        iBeamRect;
  559.  
  560.     wdPtr = (WindowDataPtr) FrontWindow(); /* Adjust the cursor only when we are in front */
  561.     if (!gInBackground && !daInFront)
  562.         {
  563.         /* calculate regions for different cursor shapes */
  564.         SetRectRgn(iBeamRgn, 0,0,0,0);
  565.         /* start arrowRgn wide open */
  566.         SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
  567.  
  568.         /* calculate iBeamRgn */
  569.         if (IsMultiCursorWindow(wdPtr))
  570.             {
  571.             /* GetYourTextRect(wdPtr, &iBeamRect); - not implemented,
  572.             should replace next line. */
  573.             iBeamRect = ((WindowPeek)wdPtr)->port.portRect;
  574.             RectRgn(iBeamRgn, &iBeamRect);
  575.             SectRgn(iBeamRgn, ((WindowPtr)wdPtr)->visRgn, iBeamRgn);
  576.             /* make a global version of the iBeamRgn */
  577.             OffsetRgn(iBeamRgn,-((WindowPtr)wdPtr)->portBits.bounds.left,
  578.                     -((WindowPtr)wdPtr)->portBits.bounds.top);
  579.             }
  580.  
  581.         /* subtract other regions from arrowRgn */
  582.         DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
  583.  
  584.         /* change the cursor and the region parameter */
  585.         if (PtInRgn(mouse, iBeamRgn) )
  586.             {
  587.             SetCursor(*IBeam);
  588.             CopyRgn(iBeamRgn, region);
  589.             }
  590.         else
  591.             {
  592.             InitCursor();
  593.             CopyRgn(arrowRgn, region);
  594.             }
  595.         }
  596.     }
  597.  
  598. Boolean    IsMultiCursorWindow(WindowDataPtr wdPtr)
  599.     {
  600.     return(FALSE);
  601.     }
  602.  
  603. /* SetWatchCursor - change cursor to watch, if available
  604. */
  605. void SetWatchCursor()
  606.     {
  607.     if (Watch)
  608.         SetCursor (*Watch);
  609.     else
  610.         InitCursor();
  611.     }
  612.  
  613. /* ---------------- support functions -------------- */
  614.  
  615. #ifndef _GestaltDispatch
  616. #define _GestaltDispatch                0xA0AD
  617. #endif
  618.  
  619. /* */
  620. Boolean System7Available()
  621.     {
  622.     long    sysVersion;
  623.     
  624.     if (!TrapAvailable(_GestaltDispatch))
  625.         return FALSE;
  626.     if (!Gestalt(gestaltSystemVersion,&sysVersion))
  627.         {
  628.         if (sysVersion >= 0x700)
  629.             return TRUE;
  630.         }
  631.     return FALSE;
  632.     }
  633.  
  634. /* */
  635. Boolean TrapAvailable(short theTrap)
  636.     {
  637.     TrapType        tType;
  638.     
  639.     tType = GetTrapType(theTrap);
  640.     if (tType == ToolTrap)
  641.         {
  642.         theTrap = (theTrap & 0x07FF);
  643.         if (theTrap >= NumToolboxTraps())
  644.             theTrap = _Unimplemented;
  645.         }
  646.     return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  647.     }
  648.  
  649. /* */
  650. TrapType GetTrapType(short theTrap)
  651.     {
  652.     if ((theTrap & 0x0800) > 0)
  653.         return ToolTrap;
  654.     return OSTrap;
  655.     }
  656.  
  657. /* */
  658. short NumToolboxTraps()
  659.     {
  660.     if (NGetTrapAddress(_InitGraf, ToolTrap)
  661.         == NGetTrapAddress(0xAA6E, ToolTrap))
  662.         return 0x0200;
  663.     return 0x0400;
  664.     }
  665.  
  666. void AEInstallEventHandlers()
  667.     {
  668.     AEInstallEventHandler(kCoreEventClass,
  669.         kAEOpenApplication,
  670.         (EventHandlerProcPtr) Handle_aevt_oapp,
  671.         0,
  672.         FALSE);
  673.     AEInstallEventHandler(kCoreEventClass,
  674.         kAEOpenDocuments,
  675.         (EventHandlerProcPtr) Handle_aevt_odoc,
  676.         0,
  677.         FALSE);
  678.     AEInstallEventHandler(kCoreEventClass,
  679.         kAEPrintDocuments,
  680.         (EventHandlerProcPtr) Handle_aevt_pdoc,
  681.         0,
  682.         FALSE);
  683.     AEInstallEventHandler(kCoreEventClass,
  684.         kAEQuitApplication,
  685.         (EventHandlerProcPtr) Handle_aevt_quit,
  686.         0,
  687.         FALSE);
  688.     }
  689.  
  690. void SeeIfDAIsFrontWindow()
  691.     {
  692.     WindowPeek    wP = (WindowPeek)FrontWindow();
  693.     
  694.     if (wP && (wP->windowKind < 0))
  695.         daInFront = TRUE;
  696.     else if (daInFront)
  697.         {
  698.         daInFront = FALSE;
  699.         /*ConvertScrapIfChanged(); - not implemented */
  700.         }
  701.     }
  702.  
  703. /********* For running Drag_on's concurrently, the calling application
  704. (here Minimal App) handles all the events while the Drag_on chugs away.
  705. Note that quitting is not allowed while a Drag_on is running.
  706. */
  707. void HandleOneEvent()
  708.     {
  709.     Point        where;
  710.     Boolean        gotEvent;
  711.     short        part;
  712.     
  713.     /* regular polling goes here */
  714.     SeeIfDAIsFrontWindow();
  715.     if (gInBackground)
  716.         {
  717.         /* handle being in the background */
  718.         ;
  719.         }
  720.     
  721.     gotEvent = WaitNextEvent(everyEvent, &gEvtDetails.event, GetSleep(), cursorRgn);
  722.     if (gotEvent)
  723.         {
  724.         SetEventDetails();
  725.  
  726.         AdjustCursor(gEvtDetails.event.where, cursorRgn);
  727.         
  728.         if (IsDialogEvent(&gEvtDetails.event))
  729.             HandleModelessDialog();
  730.         else
  731.             {
  732.             switch (gEvtDetails.event.what)
  733.                 {
  734.             case mouseDown:
  735.                 switch (part = FindWindow(gEvtDetails.event.where,
  736.                                 &gEvtDetails.mouseDownWindow)) 
  737.                     {
  738.                 case inDesk: 
  739.                     SysBeep(2);
  740.                 break;
  741.                 case inMenuBar:
  742.                     /* Note no quit allowed while Drag_on is running. */
  743.                     (void)DoMenu(MenuSelect(gEvtDetails.event.where));
  744.                 case inSysWindow:
  745.                     SystemClick(&gEvtDetails.event, gEvtDetails.mouseDownWindow);
  746.                 break;
  747.                 case inDrag:
  748.                 break;
  749.                 case inZoomIn:
  750.                 case inZoomOut:
  751.                 break;
  752.                 case inGrow:
  753.                 break;
  754.                 case inGoAway:
  755.                 break;
  756.                 case inContent:
  757.                 break;
  758.                 default: 
  759.                 break;
  760.                     } /* switch FindWindow */
  761.             break;
  762.             case keyDown:
  763.             case autoKey:
  764.                 
  765.             break;
  766.             case updateEvt:
  767.                 
  768.             break;
  769.             case diskEvt:
  770.                 if (HiWord(gEvtDetails.event.message) != noErr)
  771.                     {
  772.                     DILoad();
  773.                     where.h = where.v = 85;
  774.                     DIBadMount(where, gEvtDetails.event.message);
  775.                     }
  776.             break;
  777.             case activateEvt:
  778.                 
  779.             break;
  780.             case kOSEvent:
  781.                 switch((gEvtDetails.event.message >> 24) & 0xff)
  782.                     {
  783.                 case mouseMovedMessage:
  784.                     BlinkTextCursor();
  785.                 break;
  786.                 case suspendResumeMessage:
  787.                     gInBackground = (gEvtDetails.event.message & resumeFlag) == 0;
  788.                 break;
  789.                     }
  790.             break;
  791.             case kHighLevelEvent:
  792.                 AEProcessAppleEvent(&gEvtDetails.event);
  793.             break;
  794.                 } /* switch */
  795.             } /* not modeless dialog */
  796.         } /* if got event */
  797.     else
  798.         BlinkTextCursor();
  799.     AdjustCursor(gEvtDetails.event.where, cursorRgn);
  800.     }
  801.